package com.example.diffservice.algorithm;

import com.example.common.constant.Constants;
import com.example.diffservice.algorithm.base.common.Global;
import com.example.diffservice.algorithm.base.generatingactions.GeneratingActionsData;
import com.example.diffservice.algorithm.base.generatingactions.JavaParserTreeGenerator;
import com.example.diffservice.algorithm.base.generatingactions.MyActionGenerator;
import com.example.diffservice.algorithm.base.generatingactions.SimpleActionPrinter;
import com.example.diffservice.algorithm.base.miningactions.ActionAggregationGenerator;
import com.example.diffservice.algorithm.base.miningactions.bean.MiningActionData;
import com.example.diffservice.algorithm.base.miningchangeentity.ChangeEntityData;
import com.example.diffservice.algorithm.base.miningchangeentity.ChangeEntityPreprocess;
import com.example.diffservice.algorithm.base.miningchangeentity.base.ChangeEntityDesc;
import com.example.diffservice.algorithm.base.preprocessingfile.AddOrRemoveFileProcessing;
import com.example.diffservice.algorithm.base.preprocessingfile.FilePairPreDiff;
import com.example.diffservice.algorithm.base.preprocessingfile.data.FileOutputLog;
import com.example.diffservice.algorithm.base.preprocessingfile.data.PreprocessedData;
import lombok.SneakyThrows;
import org.json.JSONArray;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;


public class Core {

    public ChangeEntityData changeEntityData;
    public FileOutputLog mFileOutputLog;

    public void dooDiffFile(String filePrev, String fileCurr, String output) {
        int index = filePrev.lastIndexOf('/');
        String fileName = filePrev.substring(index+1,filePrev.length());
        Global.fileName = fileName;
        FilePairPreDiff preDiff = new FilePairPreDiff();
        preDiff.initFilePath(filePrev,fileCurr);
        int result = preDiff.compareTwoFile();
        if(result ==-1){
            return;
        }
        runDiff(preDiff,fileName);
    }


    public void dooDiffFile(String fileName, byte[] filePrevContent, byte[] fileCurrContent, String output) {
        long start = System.nanoTime();
        // 1.pre
        FilePairPreDiff preDiff = new FilePairPreDiff();
        preDiff.initFileContent(filePrevContent,fileCurrContent);
        int result = preDiff.compareTwoFile();
        long end = System.nanoTime();
        System.out.println("----pre-processing " +(end-start));
        if(result ==-1){
            return;
        }
        runDiff(preDiff,fileName);
    }

    @SneakyThrows
    public void dooAddFile(String fileName, byte[] fileCurrContent, String output){
        AddOrRemoveFileProcessing addOrRemoveFileProcessing = new AddOrRemoveFileProcessing(fileCurrContent, ChangeEntityDesc.StageIIIFile.DST);
        //may cause series of issues for types such like enum haven't been handled now.
        if(addOrRemoveFileProcessing.ced == null){
            return;
        }
        changeEntityData = addOrRemoveFileProcessing.ced;
        changeEntityData.fileName = fileName;
        GenerateChangeEntityJson.setStageIIIBean(changeEntityData);
        JSONArray json = GenerateChangeEntityJson.generateEntityJson(changeEntityData.mad);
        String fullFilename = Global.fileName;
        //D:\output\spring-framework\28224\dillonm79\a05dc97c74b20091c3905beaa0933991ad4133a2\gen\72e7ae60d43dfc38ad7335e24f28eed11d5fec4c
        String[] data = mFileOutputLog.sourceGen.split("/");
        StringBuilder projectLocation = new StringBuilder();
        for (int i = 0; i < data.length-4; i++) {
            projectLocation.append(data[i]).append("/");
        }
        projectLocation.append("curr/");
        BufferedReader reader = new BufferedReader(new FileReader(new File(projectLocation.toString() + fullFilename)));
        int lineCount = 0;
        while (reader.readLine() != null){
            lineCount++;
        }
        reader.close();
        JSONObject obj = json.getJSONObject(0);
        obj = obj.put("range", String.format("(%s,%s)", 1, lineCount));
        json = new JSONArray();
        json.put(obj);
        this.mFileOutputLog.writeEntityJson(json.toString(4));
    }

    @SneakyThrows
    public void dooRemoveFile(String fileName,byte[] fileCurrContent,String output){
        AddOrRemoveFileProcessing addOrRemoveFileProcessing = new AddOrRemoveFileProcessing(fileCurrContent,ChangeEntityDesc.StageIIIFile.SRC);
        //may cause series of issues for types such like enum haven't been handled now.
        if (addOrRemoveFileProcessing.ced == null) {
            return;
        }
        changeEntityData = addOrRemoveFileProcessing.ced;
        changeEntityData.fileName = fileName;
        JSONArray json = GenerateChangeEntityJson.generateEntityJson(changeEntityData.mad);
        String fullFilename = Global.fileName;
        String[] data = mFileOutputLog.sourceGen.split("/");
        StringBuilder projectLocation = new StringBuilder();
        for (int i = 0; i < data.length-4; i++) {
            projectLocation.append(data[i]).append("/");
        }
        projectLocation.append("prev/");
        BufferedReader reader = new BufferedReader(new FileReader(new File(projectLocation.toString() + fullFilename)));
        int lineCount = 0;
        while (reader.readLine() != null){
            lineCount++;
        }
        reader.close();
        JSONObject obj = json.getJSONObject(0);
        obj = obj.put("range", String.format("(%s,%s)", 1, lineCount));
        json = new JSONArray();
        json.put(obj);
        this.mFileOutputLog.writeEntityJson(json.toString(4));
    }


    //TODO
    private void runDiff(FilePairPreDiff preDiff,String fileName){
        long start = System.nanoTime();
        PreprocessedData preData = preDiff.getPreprocessedData();
        JavaParserTreeGenerator treeGenerator = new JavaParserTreeGenerator(preData.getSrcCu(),preData.getDstCu());
        treeGenerator.setFileName(fileName);
        //gumtree
        MyActionGenerator actionGenerator = new MyActionGenerator(treeGenerator);
        GeneratingActionsData actionsData = actionGenerator.generate();
        //print
        long end = System.nanoTime();
        System.out.println("----mapping " +(end-start));
        printActions(actionsData,treeGenerator);
        long start2 = System.nanoTime();
        MiningActionData mad = new MiningActionData(preData,actionsData,treeGenerator);
        ActionAggregationGenerator aag = new ActionAggregationGenerator();
        aag.doCluster(mad);
//correcting
        ChangeEntityData ced = new ChangeEntityData(mad);
        ChangeEntityPreprocess cep = new ChangeEntityPreprocess(ced);
        cep.preprocessChangeEntity();//1.init 2.merge 3.set 4.sub
        changeEntityData = ced;
        changeEntityData.fileName = fileName;
        long end2 = System.nanoTime();
        System.out.println("----grouping " +(end2-start2));
// json
        GenerateChangeEntityJson.setStageIIIBean(ced);
        JSONArray json = GenerateChangeEntityJson.generateEntityJson(ced.mad);
        this.mFileOutputLog.writeEntityJson(json.toString(4));
        if(Global.runningMode==0){
            System.out.println(GenerateChangeEntityJson.toConsoleString(json));
        }else {
            System.out.println(json.toString(4));
        }

    }


    private void printActions(GeneratingActionsData actionsData, JavaParserTreeGenerator treeGenerator){
        mFileOutputLog.writeTreeFile(treeGenerator.getPrettyOldTreeString(),treeGenerator.getPrettyNewTreeString());
        SimpleActionPrinter.printMyActions(actionsData.getAllActions());
    }


}
